﻿using english_sentences.Models;
using english_sentences.Services.Interface;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using english_sentences.Utilities;
using Microsoft.CognitiveServices.Speech.Transcription;

namespace english_sentences.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    [Produces("application/json")]
    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Roles = "FreeUser")]
    public class SentencesController : BaseApiController<SentencesController>
    {
        private readonly IVoiceService _voiceService;
        private readonly IBlobService _blobStoreService;
        private readonly ITranslatorService _translatorService;
        private readonly IDataStoreService<Sentence, string> _sentenceStoreService;
        private readonly IDataStoreService<UserExtend, string> _userExtendStoreService;
        private readonly IDataStoreService<ReadingRecord, string> _readingRecordStoreService;



        public SentencesController(ILogger<SentencesController> logger, IVoiceService voiceService,
            IBlobService blobStoreService, ITranslatorService translatorService,
            IDataStoreService<Sentence, string> sentenceStoreService,
            IDataStoreService<UserExtend, string> userExtendStoreService,
            IDataStoreService<ReadingRecord, string> readingRecordStoreService) : base(logger)
        {
            this._blobStoreService = blobStoreService;
            this._voiceService = voiceService;
            this._translatorService = translatorService;
            this._sentenceStoreService = sentenceStoreService;
            this._userExtendStoreService = userExtendStoreService;
            this._readingRecordStoreService = readingRecordStoreService;


        }
        [HttpGet("get")]
        public ActionResult Get()
        {
            return Ok(new { success = true, message = "ok124" });
        }
        [HttpPost("collect")]
        public async Task<ActionResult> Collect(Collection collection)
        {

            if (string.IsNullOrEmpty(collection.Text))
            {
                return BadRequest("blank text.");
            }
            try
            {
                string chineseText, englishText;

                if (checkIsChinese(collection.Text))
                {
                    chineseText = await this._translatorService.TranslateToChinese(collection.Text);
                    englishText = collection.Text;
                }
                else
                {
                    chineseText = await this._translatorService.TranslateToChinese(collection.Text);
                    englishText = collection.Text;
                }

                this._logger.LogDebug($"collection text: [{collection.VoiceType}]");
                this._logger.LogDebug($"Translated text: [{englishText},{chineseText}]");

                var result = await this._voiceService.SynthesizeAsync(englishText, collection.VoiceType);

                var url = await this._blobStoreService.SaveFile(result.Bytes);

                var no = await getNextNo();
                var userId = this.User.GetId();
                Sentence s = new Sentence
                {
                    ChapterNo = no.Item1,
                    ChineseText = chineseText,
                    EnglishText = englishText,
                    Duration = result.Duration,
                    FileUrl = url,
                    Sequence = no.Item2,
                    VoiceType = collection.VoiceType,
                    UserId = userId

                };
                this._logger.LogDebug($"Stored sentences: [{JsonConvert.SerializeObject(s)}]");

                await _sentenceStoreService.Add(s);

                return Ok(new { success = true, message = $"collected successfully. the duration of the audio is {result.Duration}, the downloaded ulr is {url}" });
            }
            catch (Exception ex)
            {
                this._logger.LogError(ex, ex.Message);
                throw new HttpResponseException(500); ;
            }
        }

        [HttpPost("modify")]
        public async Task<ActionResult> Modify(Sentence sentence)
        {
            var oldSentence = await _sentenceStoreService.Get<Sentence>(n => n.Id == sentence.Id);

            if (sentence.EnglishText != oldSentence.EnglishText || sentence.VoiceType != oldSentence.VoiceType)
            {
                var result = await this._voiceService.SynthesizeAsync(sentence.EnglishText, sentence.VoiceType);

                var url = await this._blobStoreService.SaveFile(result.Bytes);

                sentence.FileUrl = url;

                sentence.Duration = result.Duration;
            }

            this._logger.LogDebug($"modified sentences: [{JsonConvert.SerializeObject(sentence)}]");

            await _sentenceStoreService.Update(sentence);

            return Ok(new { success = true, message = $"modified successfully. the duration of the audio is {sentence.Duration}, the downloaded ulr is {sentence.FileUrl}" });
        }


        [HttpPost("remove/{id}")]
        public async Task<ActionResult> Remove(string id)
        {
            this._logger.LogDebug($"deleted sentences: [{id}]");
            var sentence = await _sentenceStoreService.Get<Sentence>(n => n.Id == id);
            await _sentenceStoreService.Delete(id);

            var userId = this.User.GetId();

            var sentences = await _sentenceStoreService.GetAll<Sentence>(n => n.UserId == userId);

            //   return (((int)total / 50) + 1, (int)total + 1);

            int i = 0;
            foreach (var s in sentences)
            {
                i++;
                var chapterNo = (int)(i / 50) + 1;
                var sequenceNo = i;
                s.ChapterNo = chapterNo;
                s.Sequence = sequenceNo;
                Task.Delay(50).Wait();
                await _sentenceStoreService.Update(s);
            }

            return Ok(new { success = true, message = $"deleted successfully." });
        }

        [HttpPost("getOne/{id}")]
        public async Task<ActionResult<Sentence>> GetOne(string id)
        {
            return await _sentenceStoreService.Get<Sentence>(n => n.Id == id);

        }

        [HttpGet("listByChapter/{chapterNo}")]
        public async Task<ActionResult<List<Sentence>>> ListByChapter(int chapterNo)
        {
            long total = await this.getSentencesCount();

            var userId = this.User.GetId();

            int totalChapterCount = ((int)total / 50) + 1;

            if (chapterNo < 1) { chapterNo = 1; }

            if (chapterNo > totalChapterCount) { chapterNo = totalChapterCount; }

            return await _sentenceStoreService.GetAll<Sentence>(n => n.ChapterNo == chapterNo && n.UserId == userId);
        }
        [HttpGet("readingRecord/{sentenceId}")]
        public async Task<int> GetReadingRecord(string sentenceId)
        {
            var userId = this.User.GetId();

            var readingRecord = (await this._readingRecordStoreService.GetAll<ReadingRecord>(n => n.SentenceId == sentenceId
            && n.UserId == userId)).FirstOrDefault();

            if (readingRecord != null)
            {
                return readingRecord.Count;
            }
            return 0;

        }
        [HttpPost("readingRecord/{sentenceId}")]
        public async Task<ActionResult> UpdateReadingRecord(string sentenceId)
        {
            var userId = this.User.GetId();
            var readingRecord = (await this._readingRecordStoreService.GetAll<ReadingRecord>(n => n.SentenceId == sentenceId
            && n.UserId == userId)).FirstOrDefault();

            if (readingRecord != null)
            {
                readingRecord.Count = readingRecord.Count + 1;
                await _readingRecordStoreService.Update(readingRecord);
                return Ok(new { success = true, message = $"updated successfully." });
            }
            else
            {
                readingRecord = new ReadingRecord { Count = 0, UserId = userId, SentenceId = sentenceId };
                await _readingRecordStoreService.Add(readingRecord);
                return Ok(new { success = true, message = $"added successfully." });
            }
        }


        [HttpGet("userExtend")]
        public async Task<ActionResult<UserExtend>> GetUserExtend()
        {
            var userId = this.User.GetId();
            var list = await _userExtendStoreService.GetAll<UserExtend>(n => n.UserId == userId);

            var totalQuantity = await this.getSentencesCount();

            var result = list.FirstOrDefault() ?? new UserExtend
            {
                CurrentChapterNo = 1,
                CurrentSequenceNo = 1,
                AutoPlaying = true,
                WaitTime = 5,
            };

            result.TotalQuantity = totalQuantity;

            return result;


        }
        [HttpPost("userExtend")]
        public async Task<ActionResult> UpdateUserExtend(UserExtend userExtend)
        {
            var userId = this.User.GetId();

            var list = await _userExtendStoreService.GetAll<UserExtend>(n => n.UserId == userId);

            var oldUserExtend = list.FirstOrDefault();

            if (oldUserExtend == null)
            {
                var newUserExtend = new UserExtend()
                {
                    UserId = userId,
                    CurrentChapterNo = userExtend.CurrentChapterNo,
                    CurrentSequenceNo = userExtend.CurrentSequenceNo,
                    WaitTime = userExtend.WaitTime,
                    AutoPlaying = userExtend.AutoPlaying,
                };
                await _userExtendStoreService.Add(newUserExtend);
                return Ok(new { success = true, message = $"added successfully." });
            }
            else
            {
                oldUserExtend.UserId = userId;
                oldUserExtend.CurrentChapterNo = userExtend.CurrentChapterNo;
                oldUserExtend.CurrentSequenceNo = userExtend.CurrentSequenceNo;
                oldUserExtend.WaitTime = userExtend.WaitTime;
                oldUserExtend.AutoPlaying = userExtend.AutoPlaying;
                await _userExtendStoreService.Update(oldUserExtend);
                return Ok(new { success = true, message = $"updated successfully." });
            }
        }


        private async Task<long> getSentencesCount()
        {
            var userId = this.User.GetId();
            return await _sentenceStoreService.Count<Sentence>(n => n.UserId == userId);
        }
        private async Task<(int, int)> getNextNo()
        {
            long total = await this.getSentencesCount();

            return (((int)total / 50) + 1, (int)total + 1);
        }
        private bool checkIsChinese(string text)
        {
            if (string.IsNullOrEmpty(text)) return false;
            char[] c = text.ToCharArray();
            if (c.Length == 0) return false;

            if (c[0] >= 0x4e00 && c[0] <= 0x9fbb)
                return true;
            return false;
        }

        public class Collection
        {
            public string Text { get; set; }

            public string VoiceType { get; set; } = "en-US-JennyNeural";
        }

    }
}

